package com.hadooparchitecturebook.movingavg; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.StormSubmitter; import backtype.storm.generated.AlreadyAliveException; import backtype.storm.generated.InvalidTopologyException; import backtype.storm.generated.StormTopology; import backtype.storm.topology.TopologyBuilder; import backtype.storm.tuple.Fields; import com.hadooparchitecturebook.movingavg.topology.CalcMovingAvgBolt; import com.hadooparchitecturebook.movingavg.topology.ParseTicksBolt; import com.hadooparchitecturebook.movingavg.topology.StockTicksSpout; import org.apache.storm.hdfs.bolt.HdfsBolt; import org.apache.storm.hdfs.bolt.format.DefaultFileNameFormat; import org.apache.storm.hdfs.bolt.format.DelimitedRecordFormat; import org.apache.storm.hdfs.bolt.format.FileNameFormat; import org.apache.storm.hdfs.bolt.format.RecordFormat; import org.apache.storm.hdfs.bolt.rotation.FileRotationPolicy; import org.apache.storm.hdfs.bolt.rotation.FileSizeRotationPolicy.Units; import org.apache.storm.hdfs.bolt.rotation.FileSizeRotationPolicy; import org.apache.storm.hdfs.bolt.rotation.TimedRotationPolicy; import org.apache.storm.hdfs.bolt.sync.CountSyncPolicy; import org.apache.storm.hdfs.bolt.sync.SyncPolicy; /** * Create topology to calculate moving averages over stock data. */ public class MovingAvgLocalTopologyRunner { public static void main(String[] args) { Config config = new Config(); config.setDebug(true); StormTopology topology = buildTopology(); // Un-comment to run locally: LocalCluster localCluster = new LocalCluster(); localCluster.submitTopology("local-moving-avg", config, topology); // Un-comment to run as part of a Storm cluster: // try { // StormSubmitter.submitTopology("cluster-moving-average", // config, // topology); // } catch(AlreadyAliveException e) { // e.printStackTrace(); // } catch(InvalidTopologyException e) { // e.printStackTrace(); //} } /** * Return the object creating our moving average topology. */ private static StormTopology buildTopology() { TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("stock-ticks-spout", new StockTicksSpout()); builder.setBolt("hdfs-persister-bolt", createHdfsBolt()) .shuffleGrouping("stock-ticks-spout"); builder.setBolt("parse-ticks", new ParseTicksBolt()) .shuffleGrouping("stock-ticks-spout"); builder.setBolt("calc-moving-avg", new CalcMovingAvgBolt(), 2) .fieldsGrouping("parse-ticks", new Fields("ticker")); return builder.createTopology(); } /** * Create bolt which will persist ticks to HDFS. */ private static HdfsBolt createHdfsBolt() { // Use "|" instead of "," for field delimiter: RecordFormat format = new DelimitedRecordFormat() .withFieldDelimiter("|"); // sync the filesystem after every 1k tuples: SyncPolicy syncPolicy = new CountSyncPolicy(100); // Rotate files when they reach 5MB: FileRotationPolicy rotationPolicy = new FileSizeRotationPolicy(5.0f, Units.MB); // Write records to <user>/stock-ticks/ directory in HDFS: FileNameFormat fileNameFormat = new DefaultFileNameFormat() .withPath("stock-ticks/"); HdfsBolt hdfsBolt = new HdfsBolt() .withFsUrl("hdfs://localhost:8020") .withFileNameFormat(fileNameFormat) .withRecordFormat(format) .withRotationPolicy(rotationPolicy) .withSyncPolicy(syncPolicy); return hdfsBolt; } }